home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Programming / SWI / source / src / pl-dwim.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-07  |  5.3 KB  |  221 lines

  1. /*  $Id: pl-dwim.c,v 1.11 1997/08/07 07:57:46 jan Exp $
  2.  
  3.     Copyright (c) 1990 Jan Wielemaker. All rights reserved.
  4.     See ../LICENCE to find out about your rights.
  5.     jan@swi.psy.uva.nl
  6.  
  7.     Purpose: Do What I Mean support functions
  8. */
  9.  
  10. #include "pl-incl.h"
  11. #include "pl-ctype.h"
  12.  
  13. forwards atom_t    dwimMatch(char *, char *);
  14. forwards bool    oneTypo(char *, char *);
  15. forwards bool    twoTransposed(char *, char *);
  16. forwards bool    oneInserted(char *, char *);
  17. forwards bool    differentSeparated(char *, char *);
  18. forwards char *    subWord(char *, char *);
  19. forwards bool    subwordsTransposed(char *, char *);
  20.  
  21. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  22. Strings are supposed to be meant identical iff one of the  following  is
  23. the case:
  24.  
  25.   - They ARE identical
  26.   - One character is different            (spy == spu)
  27.   - One character is inserted/deleted/added    (debug == deug)
  28.   - Two adjecent characters are transposed    (trace == tarce)
  29.   - `Sub-words' have been separated wrong    (aB == a_b == ab)
  30.   - Two `Sub-words' have been transposed    (exists_file == file_exists)
  31. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  32.  
  33. static atom_t
  34. dwimMatch(char *str1, char *str2)
  35. { int cl=0, l1, l2;
  36.   register char *s1 = str1;
  37.   register char *s2 = str2;
  38.  
  39.   while(*s1 && *s1 == *s2)            /* delete common part */
  40.     s1++, s2++, cl++;
  41.   l2 = (int) strlen(s2);
  42.   l1 = (int) strlen(s1);
  43.  
  44.   if (abs(l1-l2) > 5)                /* speed up a bit */
  45.     fail;
  46.   
  47.   if ( l1 == 0 && l2 == 0 )            return ATOM_equal;
  48.   if ( cl + l1 < 3 || cl + l2 < 3 )
  49.     fail;
  50.   if ( l1 == l2 && oneTypo(s1, s2) )        return ATOM_mismatched_char;
  51.   if ( l1 == l2 && twoTransposed(s1, s2) )    return ATOM_transposed_char;
  52.   if ( (l2 == l1 + 1 && oneInserted(s1, s2)) ||
  53.        (l1 == l2 + 1 && oneInserted(s2, s1)) )    return ATOM_inserted_char;
  54.   if ( differentSeparated(str1, str2) )        return ATOM_separated;
  55.   if ( subwordsTransposed(str1, str2) )        return ATOM_transposed_word;
  56.  
  57.   fail;
  58. }
  59.  
  60. static bool
  61. oneTypo(char *s1, char *s2)
  62. { if (s1[1] == EOS || streq(&s1[1], &s2[1]) )
  63.     succeed;
  64.   fail;
  65. }
  66.  
  67. static
  68. bool
  69. twoTransposed(register char *s1, register char *s2)
  70. { if (s1[1] != EOS && s1[0] == s2[1] && s1[1] == s2[0] &&
  71.        (s1[2] == EOS || streq(&s1[2], &s2[2])))
  72.     succeed;
  73.   fail;
  74. }
  75.  
  76. static bool
  77. oneInserted(register char *s1, register char *s2)
  78. { if (streq(s1, &s2[1]) )
  79.     succeed;
  80.   fail;
  81. }
  82.  
  83. static bool
  84. differentSeparated(register char *s1, register char *s2)
  85. { register char c1, c2;
  86.  
  87.   if ( *s1 != *s2 || *s1 == EOS )
  88.     fail;
  89.  
  90.   c1 = *++s1, c2 = *++s2;
  91.   while(c1 && c1 == c2)
  92.   { if ((c1 = *++s1) == '_')
  93.     { c1 = *++s1;
  94.     } else
  95.     { if (isLower(s1[-1]) && isUpper(c1))
  96.         c1 = makeLower(c1);
  97.     }
  98.     if ((c2 = *++s2) == '_')
  99.     { c2 = *++s2;
  100.     } else
  101.     { if (isLower(s2[-1]) && isUpper(c2))
  102.     c2 = makeLower(c2);
  103.     }
  104.   }
  105.   if (c1 == EOS && c2 == EOS)
  106.     succeed;
  107.   fail;
  108. }
  109.  
  110. static char *
  111. subWord(register char *s, register char *store)
  112. { *store++ = makeLower(*s);
  113.   s++;
  114.  
  115.   for(;;)
  116.   { if (*s == EOS)
  117.     { *store = EOS;
  118.       return s;
  119.     }
  120.     if (*s == '_')
  121.     { *store = EOS;
  122.       return ++s;
  123.     }
  124.     if (isLower(s[-1]) && isUpper(s[0]) )
  125.     { *store = EOS;
  126.       return s;
  127.     }
  128.     *store++ = *s++;
  129.   }
  130. }    
  131.  
  132. static bool
  133. subwordsTransposed(char *s1, char *s2)
  134. { char sw1a[1024], sw1b[1024];
  135.   char sw2a[1024], sw2b[1024];
  136.  
  137.   while(*s1 && *s2)
  138.   { s1 = subWord(s1, sw1a);
  139.     s2 = subWord(s2, sw2a);
  140.     if (!streq(sw1a, sw2a) )
  141.     { if (*s1 == EOS || *s2 == EOS)
  142.     fail;
  143.       s1 = subWord(s1, sw1b);
  144.       s2 = subWord(s2, sw2b);
  145.       if (!streq(sw1a, sw2b) || !streq(sw1b, sw2a) )
  146.     fail;
  147.     }
  148.   }
  149.   if (*s1 == EOS && *s2 == EOS)
  150.     succeed;
  151.   fail;
  152. }
  153.  
  154.         /********************************
  155.         *       PROLOG CONNECTION       *
  156.         *********************************/
  157.  
  158. word
  159. pl_dwim_match(term_t a1, term_t a2, term_t mm)
  160. { char *s1, *s2;
  161.   atom_t type;
  162.  
  163.   if ( PL_get_chars(a1, &s1, CVT_ALL|BUF_RING) &&
  164.        PL_get_chars(a2, &s2, CVT_ALL|BUF_RING) &&
  165.        (type = dwimMatch(s1, s2)) &&
  166.        PL_unify_atom(mm, type) )
  167.     succeed;
  168.     
  169.   fail;
  170. }
  171.  
  172. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  173. $dwim_predicate(+Term, -Dwim) successively returns all predicates of the
  174. specified module or context module  that  match  in  a  DWIM  sence  the
  175. predicate head.
  176. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  177.  
  178. word
  179. pl_dwim_predicate(term_t pred, term_t dwim, word h)
  180. { functor_t fdef;
  181.   Module module = (Module) NULL;
  182.   Procedure proc;
  183.   Symbol symb;
  184.   term_t head = PL_new_term_ref();
  185.  
  186.   if ( ForeignControl(h) == FRG_CUTTED )
  187.     succeed;
  188.  
  189.   if ( !PL_strip_module(pred, &module, head) )
  190.     fail;
  191.   if ( !PL_get_functor(head, &fdef) )
  192.     return warning("dwim_predicate/2: instantiation fault");
  193.       
  194.   if ( ForeignControl(h) == FRG_FIRST_CALL )
  195.     symb = firstHTable(module->procedures);
  196.   else
  197.     symb = ForeignContextPtr(h);
  198.  
  199.   for(; symb; symb = nextHTable(module->procedures, symb))
  200.   { Definition def;
  201.     char *name;
  202.  
  203.     proc = (Procedure) symb->value;
  204.     def  = proc->definition;
  205.     name = stringAtom(def->functor->name);
  206.  
  207.     if ( dwimMatch(stringAtom(nameFunctor(fdef)), name) &&
  208.          isDefinedProcedure(proc) &&
  209.          (name[0] != '$' || SYSTEM_MODE) )
  210.     { if ( !PL_unify_functor(dwim, def->functor->functor) )
  211.     continue;
  212.       if ( (symb = nextHTable(module->procedures, symb)) )
  213.     ForeignRedoPtr(symb);
  214.  
  215.       succeed;
  216.     }
  217.   }
  218.  
  219.   fail;
  220. }
  221.